/**
 * The Woosta Table Football Engine
 *
 * License... etc.
 **
 * Shader Base
 *
 * Provides the following
 *	- Interface to Cg routines for the creation
 *	  of pixel and vertex shaders
 **
 * Author: Sean Micklethwaite
 **/

#ifndef __shaderH__
#define __shaderH__

#include "kernel.h"
#include "wtftypes.h"
#include "vector.h"
#include "data.h"
#include <Cg/cg.h>

namespace WtfEngine{
	/** Base for Cg shaders */
	class ShaderBase : public DataObject
	{
	public:
		typedef enum{
			FROM_FILE = 1,
			SOURCE_CODE = 2
		}tShaderType;

	protected:
		CGprogram	mCgVProgram, mCgFProgram;

		static CGcontext	gCgContext;
		static CGprofile	gCgGeometryProfile, gCgVertexProfile, gCgFragmentProfile;
		static bool			gCgInitialized;

	public:
		// TODO - sort this out.
		ShaderBase(tString sName, tString sVp, tString sFp,
				tString sShaderSrc, int shaderType)
				: DataObject(StringPool::GetInstance()[sName]){
			Create(sVp, sFp, sShaderSrc, shaderType);
		};

		virtual ~ShaderBase() {};

		
		void Create(tString sVp, tString sFp, tString sShaderSrc, int shaderType);
		
		virtual void Update() {};

		void Enable();
		void Disable();

	protected:
		void Init();

		CGparameter	GetParam(tString sName, bool bFp = false);

		void CheckCgError(tString sMsg){
			CGerror error;
			const char *s = cgGetLastErrorString(&error);

			if (error != CG_NO_ERROR) {
				std::cerr << "Cg error in " << ((String)getName()).c_str() << ": " << s << "\nWhen " << sMsg;
				if (error == CG_COMPILER_ERROR)
					std::cerr << "\n" << cgGetLastListing(gCgContext);

				throw "Cg Error";
			}
		};

	private:
		CGprogram LoadProgram(tString sName, tString sShaderSrc, int shaderType, bool bFp);

		DATA_OBJECT(ShaderBase, sizeof(ShaderBase));
	};

	class VertexLight : public DataObject
	{
	protected:
		tVector	mDiffuse;

	public:
		VertexLight(){
			
		};
	};

	class VertexLighting : public ShaderBase
	{
	protected:
		/*** Shader parameters ***/
		CGparameter modelViewMatrix;
		CGparameter globalAmbient;
		CGparameter lightColor;
		CGparameter lightPosition;
		CGparameter eyePosition;
		CGparameter Ke;
		CGparameter Ka;
		CGparameter Kd;
		CGparameter Ks;
		CGparameter shininess;

	public:
		VertexLighting();
		virtual ~VertexLighting() {};

		void Update();
	};

	class HdrDownsampler : public ShaderBase
	{
	protected:
		/*** Shader parameters ***/
		CGparameter mparamGamma;
		CGparameter mparamExposure;

	public:
		HdrDownsampler();
		virtual ~HdrDownsampler() {};

		void SetExposure(tScalar e);

		DATA_OBJECT(HdrDownsampler, sizeof(HdrDownsampler));
	};

	class HdrExposure : public ShaderBase
	{
	public:
		HdrExposure();
		virtual ~HdrExposure() {};

		DATA_OBJECT(HdrExposure, sizeof(HdrExposure));
	};
};

#endif
